package com.oasys.service.impl;

import com.oasys.dao.EmployMapper;
import com.oasys.dao.MenuMapper;
import com.oasys.dao.SysRoleMapper;
import com.oasys.dao.SysUserMapper;
import com.oasys.ecxeption.BusinessException;
import com.oasys.entity.*;
import com.oasys.entity.vo.UserAccountVo;
import com.oasys.service.SysUserService;
import com.oasys.utils.AutoGenerateIds;
import com.oasys.utils.PasswordUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author mis_wu
 * 系统用户
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class SysUserServiceImpl implements SysUserService {

    private final static ThreadLocal<LoginUser> USER_THREAD_LOCAL = new ThreadLocal<>();
    private final static Map<String, UserInfo> TOKEN_MAP = new HashMap<>(100);

    /**
     * 过期时间一小时
     */
    private final static Long EXPIRE_HOUR = 6000 * 1000 * 1000L;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private SysRoleMapper sysRoleMapper;

    @Resource
    private MenuMapper menuMapper;

    @Resource
    private EmployMapper employMapper;

    @Override
    public String signIn(String userAccount, String password) {
        if (StringUtils.isAnyBlank(userAccount, password)) {
            throw new BusinessException("用户名或密码不能为空");
        }

        SysUserEntity user = sysUserMapper.findByUserAccount(userAccount);
        if (user == null || !PasswordUtils.check(password, user.getPasswordHash(), user.getPasswordSalt())) {
            throw new BusinessException("用户名或密码错误");
        }

        if (!isAvailable(user)) {
            throw new BusinessException("该用户已被禁用");
        }

        setLoginUser(user.getUserId());

        return createToken(user.getUserId());
    }

    @Override
    public void setLoginUser(String token) {
        UserInfo userInfo = TOKEN_MAP.get(token);
        if (userInfo == null || userInfo.getUserId() == null) {
            throw new BusinessException("请登录");
        }
        Long timestamp = userInfo.getTimestamp();
        if (timestamp == null || System.currentTimeMillis() - timestamp > EXPIRE_HOUR) {
            throw new BusinessException("请重新登录");
        }
        setLoginUser(userInfo.getUserId());
    }

    @Override
    public void setLoginUser(Long userId) {
        SysUserEntity user = sysUserMapper.findById(userId);
        if (!isAvailable(user)) {
            throw new BusinessException("该用户已不可用");
        }

        List<SysRoleEntity> roles = sysRoleMapper.findByUserId(user.getUserId());
        if (roles == null || roles.isEmpty()) {
            throw new BusinessException("该用户没有有效的角色");
        }

        SysRoleEntity role = roles.get(0);

        LoginUser loginUser = new LoginUser();
        loginUser.setUserId(user.getUserId());
        loginUser.setUserName(user.getUserName());
        loginUser.setUserAccount(user.getUserAccount());
        loginUser.setFlagInvalid(user.getFlagInvalid());
        loginUser.setRoleId(role.getRoleId());
        loginUser.setRoleName(role.getRoleName());
        loginUser.setTokenList(getRolesList(role.getRoleId()));

        USER_THREAD_LOCAL.set(loginUser);
    }

    @Override
    public LoginUser getLoginUser() {
        return USER_THREAD_LOCAL.get();
    }

    private boolean isAvailable(SysUserEntity user) {
        return user != null && user.getFlagInvalid() != null && user.getFlagInvalid() != 1;
    }

    private String createToken(Long userId) {
        String token = UUID.randomUUID().toString().replace("-", "");
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(userId);
        userInfo.setTimestamp(System.currentTimeMillis());
        TOKEN_MAP.put(token, userInfo);
        return token;
    }

    private List<String> getRolesList(Long roleId) {
        List<SysMenuEntity> menus = menuMapper.findMenusByRoleId(roleId);
        if (menus == null || menus.isEmpty()) {
            return Collections.emptyList();
        }
        Set<String> tokenSet = new HashSet<>();
        for (SysMenuEntity menu : menus) {
            if (menu == null || menu.getMenuType() == null || menu.getMenuType() != 0) {
                continue;
            }
            tokenSet.add(menu.getMenuCode());
        }
        return new ArrayList<>(tokenSet);
    }

    /**
     * 获取name
     * @param userId
     * @return
     */
    @Override
    public String getStaffName(Long userId){
        return sysUserMapper.getStaffName(userId);
    }

    @Data
    private static class UserInfo {
        private Long userId;
        private Long timestamp;
    }

    /**
     * 创建新账户
     * @param userAccountVo vo
     * @return boolean
     */
    @Override
    public Boolean userAccountAssignment(UserAccountVo userAccountVo) {
        Boolean result = false;
        //组装账号信息 sys_user
        SysUserEntity sysUserEntity = new SysUserEntity();
        sysUserEntity.setUserId(AutoGenerateIds.getGenerateId());
        sysUserEntity.setUserAccount(userAccountVo.getUserAccount());
        sysUserEntity.setUserName(userAccountVo.getStaffName());
        //密码盐值
        String pwdSalt = PasswordUtils.rndSalt();
        sysUserEntity.setPasswordSalt(pwdSalt);
        //密码哈希值
        sysUserEntity.setPasswordHash(PasswordUtils.hash(userAccountVo.getPassword(),pwdSalt));
        sysUserEntity.setFlagInvalid(0);
        result = sysUserMapper.saveUserAccount(sysUserEntity);
        //用户状态信息 no: 1在职  2离职  3停薪留职
        Long stateId = sysUserMapper.getStateIdByNo(1);
        //用户扩展信息
        EmployPo employPo = new EmployPo();
        employPo.setSid(AutoGenerateIds.getGenerateId());
        employPo.setUserId(sysUserEntity.getUserId());
        employPo.setStaffName(userAccountVo.getStaffName());
        employPo.setStaffAge(userAccountVo.getStaffAge());
        employPo.setStaffSex(userAccountVo.getStaffSex());
        employPo.setStaffSal(userAccountVo.getStaffSal());
        employPo.setStaffTel(userAccountVo.getStaffTel());
        employPo.setShireDate(userAccountVo.getShireDate());
        employPo.setJobId(userAccountVo.getJobId());
        employPo.setDeptId(userAccountVo.getDeptId());
        employPo.setStaffDate(userAccountVo.getStaffDate());
        employPo.setStaffAddress(userAccountVo.getStaffAddress());
        employPo.setStateId(stateId);
        employPo.setSnickName(userAccountVo.getUserAccount());
        employPo.setStaffPwd(userAccountVo.getPassword());
        result = employMapper.saveStaffExpansion(employPo);
        //角色信息
        SysUserRoleEntity sysUserRoleEntity = new SysUserRoleEntity();
        sysUserRoleEntity.setUserRoleId(AutoGenerateIds.getGenerateId());
        sysUserRoleEntity.setUserId(sysUserEntity.getUserId());
        sysUserRoleEntity.setRoleId(userAccountVo.getJobId());
        result = sysRoleMapper.saveUserRole(sysUserRoleEntity);
        return result;
    }
}






















